package com.hmdp.service.impl;

import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisIdWorker;
import com.hmdp.utils.SimpleRedisLock;
import com.hmdp.utils.UserHolder;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Resource
    private ISeckillVoucherService seckillVoucherService;
    @Resource
    //注入全局ID生成器
    private RedisIdWorker redisIdWorker;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result seckill(Long voucherId) {
        //查询优惠券
        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
        //判断秒杀是否开始和结束
        if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
            return Result.fail("秒杀活动尚未开始!");
        }
        if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
            return Result.fail("sorry~ 秒杀活动已结束。");
        }
        //开始之后检查库存是否充足
        if (voucher.getStock() < 1) {
            return Result.fail("sorry~ 库存不足哦~");
        }
        Long userId = UserHolder.getUser().getId();//获取用户id,给同一个用户的id进行加锁

        //创建锁对象
        SimpleRedisLock lock = new SimpleRedisLock("order" + userId, stringRedisTemplate);
        //获取锁
        boolean isLock = lock.tryLock(1200);
        if(!isLock){
            //获取锁失败, 返回错误
            return Result.fail("不允许重复下单!");
        }
        try {
            //拿到事务代理对象
            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
            return proxy.createVoucherOrder(voucherId);
        } finally {
            lock.unlock();
        }

//        //先获取锁,等提交完事务之后再次释放锁才能确保线程安全
//        synchronized (userId.toString().intern()) {
//            //拿到事务代理对象
//            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
//            return proxy.createVoucherOrder(voucherId);
//        }
    }

    @Transactional
    public Result createVoucherOrder(Long voucherId) {
        //设置一人一单 (解决一人多单问题,使用synchronized悲观锁)
        Long userId = UserHolder.getUser().getId();

        //查询订单
        Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
        //判断订单是否存在
        if(count > 0) {
            return Result.fail("您已经购买过了!");
        }

        //扣减库存
        boolean success = seckillVoucherService.update().
                setSql("stock = stock - 1") //set stock = stock - 1
                .eq("voucher_id", voucherId) // where voucher_id = ? and stock > 0
                .gt("stock", 0).update(); //使用乐观锁解决库存超卖问题

        if (!success) {
            return Result.fail("sorry~ 库存扣减失败哦~");
        }
        //创建订单，返回订单
        VoucherOrder voucherOrder = new VoucherOrder();
        //设置订单ID
        long orderId = redisIdWorker.nextId("order");
        voucherOrder.setId(orderId);
        //设置用户ID
        voucherOrder.setUserId(userId);
        //设置代金券Id
        voucherOrder.setVoucherId(voucherId);
        //写入数据库
        save(voucherOrder);
        return Result.ok(orderId);
    }

}
